"""
wow.apis.item
=============

Classes representing items in the Armory.

"""

from wow.core import ArmoryInterface, BasicContainer, RecursionContainer, replace_keys
from wow.exceptions import *

class Item(ArmoryInterface):
    """
    Item
    ====
    
    The class representing, quite simply, an item. Note that this is
    not the class used for equipped items (see ``EquippedItem``),
    and therefore does not contain information about enchantments,
    gems, et cetera.
    
    """
    def __init__(self, tooltip, info, api=None, region=None):
        """
        __init__(self, tooltip, info, api=None, region=None) -> Item
        Initialise the item, also loading its data from the Armory.
        
        """
        ArmoryInterface.__init__(self, api, region)
        self.info = ItemInfo(info, api, region)
        self.tooltip = ItemTooltip(tooltip, api, region)
    
    def __getattr__(self, attribute):
        """
        __getattr__(self, attribute) -> ?
        Search for an attribute within the ``info`` and ``tooltip``
        attributes, in order to "flatten" the object. Credit goes to
        Wowr for the idea.
        
        todo(?): add direct ``self.info.bonus_stats`` lookup?
        
        """
        try:
            return getattr(self.tooltip, attribute)
        except AttributeError:
            try:
                return getattr(self.info, attribute)
            except AttributeError, e:  # hackish way of raising the exception that was left unraised before
                raise AttributeError('%s object has no attribute %s' % (repr(self.__class__.__name__), repr(attribute)))

class ItemInfo(ArmoryInterface):
    """
    ItemInfo
    ========
    
    A class representing the (very limited) item information from
    ``item-info.xml`` pages.
    
    """
    def __init__(self, tree, api=None, region=None):
        """
        ItemInfo.__init__(self,) -> ItemInfo
        Initialise the ``ItemInfo`` class, retrieving and storing
        all needed information.
        
        """
        ArmoryInterface.__init__(self, api, region)

class ItemTooltip(ArmoryInterface):
    """
    ItemTooltip
    ===========
    
    A class representing the (more informatino-rich) item info
    from ``item-tooltip.xml`` pages (the main part of the item data).
    
    """
    def __init__(self, tree, api=None, region=None):
        """
        ItemTooltip.__init__(self, tree, api=None, region=None) -> ItemTooltip
        Initialise the ``ItemTooltip``, retrieving and storing all
        needed information.
        
        """
        ArmoryInterface.__init__(self, api, region)
        tree = tree.itemTooltips.itemTooltip  # bleugh @ Blizzard's redundancy
        self.name = tree.name[0]
        self.icon = tree.icon[0]
        self.quality = self.overall_quality_id = int(tree.overallQualityId[0])
        self.bonding = bool(tree.bonding[0])
        self.class_id = int(tree.classId[0])
        self.equip_data = RecursionContainer(tree.equipData)
        self.damage_data = RecursionContainer(tree.damageData) or None
        self.armor = hasattr(tree, 'armor') and int(tree.armor[0]) or None
        
        self.bonus_stats = BasicContainer((stat[5:].lower(), hasattr(tree, stat) and int(tree[stat][0]) or None) for stat in ('bonusAgility', 'bonusIntellect', 'bonusSpirit', 'bonusStrength', 'bonusStamina'))
        
        self.allowable_classes = RecursionContainer(tree.allowableClasses)

class DamageData(BasicContainer):
    """
    DamageData
    ==========
    
    A container for damage data about weapons - this includes speed,
    min/max damage and DPS.
    
    """
    def __init__(self, element):
        """
        DamageData.__init__(self, element) -> DamageData
        
        """
        if not element._dir:  # it's not a weapon
            return
        
        self['damage'] = BasicContainer()
        self['min'] = self.damage['min'] = int(element.damage.min[0])
        self['max'] = self.damage['max'] = int(element.damage.max[0])
        self['type'] = self.damage['type'] = int(element.damage.type[0])
        self['speed'] = float(element.speed[0])
        self['dps'] = float(element.dps[0])
